#!/bin/bash
#发布环境类型
ENV=$1
DOCKER_NAMES=$(docker ps --format '{{.Names}}')
#判断是否拥有公共服务环境
HAD_ENV=0
#应用名称
APP_NAME=$2
#应用需要的环境变量
APP_ENV="test=1"
#是否横向拓展应用，此参数从Jenkins调用时候传进来,0表示不进行横向拓展，1表示进行横向拓展应用
IS_HORIZONTAL_EXPANSION=$3
#目标服务器IP
DEPLOY_IP=$4
#应用端口
APP_PORT=$5
APP_DOCKER_IP=0.0.0.0
DEPLOY_HOME=/home/jenkins/${ENV}/${APP_NAME}/deploy
#构建编号
BUILD_NUMBER=$6
#随机端口
RAND_PORT=8000
#健康检测url
HEALTH_URL="/actuator/health"


#帮助信息函数
usage(){
    cat <<EOF
usage: $0 [-u openids -s summary -n name -t time -d detail -l link] [-h]
    u   wechat user openid , multiple comma separated
    s   message summary
    n   project name
    t   alarm time
    d   message detail
    l   link address
    h   output this help and exit
EOF
}

rand(){
    min=$1
    max=$(($2-$min+1))
    num=$(cat /dev/urandom | head -n 10 | cksum | awk -F ' ' '{print $1}')
    echo $(($num%$max+$min))
}

test_env(){
	if [ ! -d /data/$ENV/ ];then
		echo "/data/$ENV/ 不存在"
		echo "创建/data/$ENV/目录"
		mkdir -p /data/$ENV
	fi
	echo "--------------test_ENV"
	#检测是否有公共组件映射的目录以及配置文件
	
	if [ ! -d /data/$ENV/nginx1.18 ];then
		echo "不存在/data/$ENV/nginx1.18"
		cp -r ./soft/nginx1.18 /data/$ENV/
	fi
	
	if [ ! -d /data/$ENV/mongo ];then
		echo "不存在/data/$ENV/mongo"
		cp -r ./soft/mongo /data/$ENV/
	fi
	
	if [ ! -d /data/$ENV/nacos-server ];then
		echo "不存在/data/$ENV/nacos-server"
		cp -r ./soft/nacos-server /data/$ENV/
	fi
	
	if [ ! -d /data/$ENV/redis ];then
		echo "不存在/data/$ENV/redis"
		cp -r ./soft/redis /data/$ENV/
	fi
	
	if [ ! -d /data/$ENV/mysql ];then
		echo "不存在/data/$ENV/mysql"
		cp -r ./soft/mysql /data/$ENV/
	fi
	if [ ! -d /logs/$ENV/${APP_NAME} ];then
		echo "日志目录不存在，进行创建 /data/$ENV/$APP_NAME/logs"
		mkdir -p /logs/$ENV/${APP_NAME}
	fi
	echo "需要的软件目录检测完毕"
	#TODO检测是否安装了docker、docker-compose
	#
	
}
#检测公共服务是否完整，不完整的话，会进行构建
bulid_public_services(){
	while read line
		do 
			if [ ! $ENV_$line ]; then
					echo "读取到空行，跳过"
					continue;
				fi
			num=$(echo $DOCKER_NAMES | grep $ENV_$line |wc -l)
			if [ $num -ne 0 ];then 
				echo "$ENV_$line 容器已启动"
			else
				echo "$ENV_$line 容器未启动"
				echo "开始构建公共服务环境"
				echo "清理公共服务环境"
				docker-compose -f $ENV/docker-compose-$ENV.yml  down
				echo "开始使用docker-compose-$ENV.yml构建公共服务"
				docker-compose -f $ENV/docker-compose-$ENV.yml  up -d
				exit
			fi
		done < $DEPLOY_HOME/$ENV/public.services

}
product_app_port(){
	sum=100
	if [ $APP_PORT -ne -1 ];then
		echo "使用指定端口：$APP_PORT"
		num=$(netstat -ntlp | awk '{print $4}' |grep ${APP_PORT} |wc -l)
			if [ $num -ne 0 ];then
				echo "端口被占用，请重新指定端口"
				exit
			else 
				echo "指定端口有效"
				RAND_PORT=$APP_PORT
			fi
	else 
		echo "使用随机生成端口"
		while [ $sum -gt 0 ]
		do
			let sum--
			RAND_PORT=$(rand 8000 9000)
			echo "生成的随机端口：$RAND_PORT"
			#判断端口是否被占用
			num=$(netstat -ntlp | awk '{print $4}' |grep ${RAND_PORT} |wc -l)
			if [ $num -ne 0 ];then
				echo "端口被占用，重新调用rand"
			else 
				echo "端口有效,退出循环"
				break
			fi
			if [ $sum -e 0 ];then
				echo "端口已耗尽，请联系管理员"
			fi
		done
	fi

}

stop_app_container(){
	echo $ENV;
	docker ps  -a --format '{{.Names}}' |grep ${ENV}_${APP_NAME}* | while read line
		do
			echo "停止容器：$line"
			docker stop $line
			docker rm $line
		done 
	
}

#构建使用docker应用
build_app(){

	echo "获取到的容器名称列表：$DOCKER_ARR_NAME"
	echo "--------------构建$APP_NAME应用"
	if [ $IS_HORIZONTAL_EXPANSION == 'false' ];then
		echo "不进行横向拓展，一个应用一个容器"
		echo "移除容器:${ENV}_${APP_NAME}"
		stop_app_container
		#docker stop ${ENV}_${APP_NAME}
		docker rm ${ENV}_${APP_NAME}
		#echo "移除旧应用镜像"
		#docker rmi ${ENV}_${APP_NAME}:latest
		#在移除旧容器的情况下才生成端口，避免指定的端口和原来的旧容器端口冲突
		product_app_port
		#echo "将jar包拷贝到映射的目录，并且重启容器"
		
		#docker cp target.jar ${ENV}_${APP_NAME}:/root/
		#echo "使用dockerfile构建应用镜像"
		docker build -t ${ENV}_${APP_NAME}:latest  -f $ENV/Dockerfile .
		#DOCKER_ID=$(docker run -itd -p ${RAND_PORT}:${RAND_PORT} --log-driver=fluentd  --log-opt fluentd-address=${FLUENTD_IP}  -v /etc/localtime:/etc/localtime:ro --log-opt tag="${ENV}_${APP_NAME}_${BUILD_NUMBER}" --net host --name  ${ENV}_${APP_NAME} ${ENV}_${APP_NAME}:latest bash -c "java -jar -Dserver.port=${RAND_PORT} /root/target.jar")
		DOCKER_ID=$(docker run -itd --restart=always -p ${RAND_PORT}:${RAND_PORT} -v /logs/$ENV/${APP_NAME}:/root/logs/ --net host --name  ${ENV}_${APP_NAME} ${ENV}_${APP_NAME}:latest bash -c "java -jar -Dserver.port=${RAND_PORT}  -Xmx256m -Xms256m -Xmn128m  /root/target.jar > /root/logs/${APP_NAME}-${BUILD_NUMBER}.log")
		#DOCKER_ID=$(docker run -itd -p ${RAND_PORT}:${RAND_PORT} -v /etc/localtime:/etc/localtime:ro  -v /logs/$ENV/${APP_NAME}:/root/logs/ --net host --name  ${ENV}_${APP_NAME} ${ENV}_${APP_NAME}:latest bash -c "java -jar -Dserver.port=${RAND_PORT}  -Xmx256m -Xms256m -Xmn128m  /root/target.jar")
		
		#获取应用服务的ip
		#APP_DOCKER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${ENV}_${APP_NAME})
		#echo "应用容器IP：$APP_DOCKER_IP"
		
		
		
	
	else 
		echo "进行横向拓展应用：${APP_NAME}"
		NEW_NAME=${ENV}_${APP_NAME}_${BUILD_NUMBER}
		echo "新应用名称：$NEW_NAME"
		product_app_port
		echo "最终生成的端口：$RAND_PORT"
		DOCKER_ID=$(docker run -itd -p ${RAND_PORT}:${RAND_PORT} -v /logs/$ENV/${APP_NAME}:/root/logs/ --net host --name  ${ENV}_${APP_NAME}_${RAND_PORT} ${ENV}_${APP_NAME}:latest bash -c "java -jar -Dserver.port=${RAND_PORT} -Xmx256m -Xms256m -Xmn128m /root/target.jar > /root/logs/${APP_NAME}-${BUILD_NUMBER}.log")
		echo "执行的docker启动命令：docker run -itd -p ${RAND_PORT}:${RAND_PORT} -v /logs/$ENV/${APP_NAME}:/root/logs/ --net host --name  ${ENV}_${APP_NAME} ${ENV}_${APP_NAME}:latest bash -c 'java -jar -Dserver.port=${RAND_PORT} -Xmx256m -Xms256m -Xmn128m /root/target.jar > /root/logs/${APP_NAME}-${BUILD_NUMBER}.log'"
		#获取应用服务的ip
		
	fi	
	sleep 20s
	echo "---------------应用的启动日志start----------------"
	cat /logs/$ENV/${APP_NAME}/${APP_NAME}-${BUILD_NUMBER}.log
	echo "---------------应用的启动日志end------------------"

	echo "应用访问地址：${DEPLOY_IP}:${RAND_PORT}"
	echo "执行成功"
	

}
#构建应用dockerfile
build_app_dockerfile(){
	echo "-------------build_app_dockerfile"
	echo "环境变量写入dockerfile"
	sed -i "3a$(echo 'ENV '$APP_ENV)\n" ${ENV}/Dockerfile
	echo "写入环境变量成功"
}
#检测服务状态
check_service(){
	
	result=$(curl http://${DEPLOY_IP}:${RAND_PORT}$HEALTH_URL  )
	echo "$result"
	num=`echo $result |grep "UP" |wc -l`
	echo "\n 行数：$num"
	if [ $num -gt 0 ];then
		echo "服务正常"
		./dingding.sh '【Jenkins构建通知】:'${JOB_NAME}' - Build #'${BUILD_NUMBER}'\n项目名称:'${JOB_NAME}'\n构建分支:'${BRANCH}'\n构建编号：'${BUILD_NUMBER}'\n构建应用：'${APP_NAME}'\n提交信息：'${CHANGE_LOG}'\n提交者：'${GIT_USER_NAME}'\n构建信息：构建成功，应用服务地址'${DEPLOY_IP}:${RAND_PORT}' \n构建状态：success'
	else
		echo "服务异常"
		./dingding.sh '【Jenkins构建通知】:'${JOB_NAME}' - Build #'${BUILD_NUMBER}'\n项目名称:'${JOB_NAME}'\n构建分支:'${BRANCH}'\n构建编号：'${BUILD_NUMBER}'\n构建应用：'${APP_NAME}'\n提交信息：'${CHANGE_LOG}'\n提交者：'${GIT_USER_NAME}'\n构建信息：构建失败 \n构建状态：failed'
		exit
	
	fi
}
main()
{

	cd $DEPLOY_HOME
	#确定docker-compose的环境变量
	echo "生成环境变量"
	rm -rf .env
	cat ./$ENV/$ENV.env  > .env
	sed  -i "s/localhost/$(echo $DEPLOY_IP)/" .env
	sed -i "s/127.0.0.1/$(echo $DEPLOY_IP)/" .env
	APP_ENV=$(sed  '/^ENV/d' .env)
	pwd && mv ../${APP_NAME}-1.0.0-${BUILD_NUMBER}.jar ./target.jar
	if [ $? -ne 0 ]; then
		echo "jar包拷贝失败"
	fi
	#检测环境是否符合运行此脚本的条件,比如是否安装了docker、docker-compose等
	#test_env
	
	#检测环境是否有完整的公共服务,并且构建公共服务
	#bulid_public_services
	echo "-------------"
	#构建应用dockerfile
	#build_app_dockerfile
	
	#不重新构建容器,替换新jar包
	docker cp target.jar ${ENV}_${APP_NAME}:/root/
	#将环境变量覆盖docker内环境变量
	docker cp .env ${ENV}_${APP_NAME}:/root/
	
	docker restart ${ENV}_${APP_NAME}
	
	
	#check_service
	

}
main